package com.googlecode.wheres_my_stuff_okay_potato;

import java.util.List;

import android.app.Application;

import com.googlecode.wheres_my_stuff_okay_potato.LoginHandler.UserNotFoundException;

/**
 * This class is a replacement for the default application class. It keeps track
 * of the login and item handlers across activites so that we don't have to keep
 * passing the username through intent extras.
 * 
 * @author Jeremy Hehn
 */
public class Global extends Application {
	private LoginHandler lh;
	private ItemHandler ih;
	private User currentUser;

	@Override
	public void onCreate() {
		lh = new LoginHandler(this.getBaseContext());
		ih = new ItemHandler(this.getBaseContext());
	}

	/**
	 * Adds a lost item to the system and to the current user's item database.
	 * The item added has a reward of $0. This calls addLostItem(String, String,
	 * String, String) using the specified item's attributes.
	 * 
	 * @param i
	 *            is the item to be added.
	 * @see addLostItem(String, String, String, String)
	 */
	public void addLostItem(LostItem i) {
		addLostItem(i.getName(), i.getDesc(), i.getLoc(), i.getItemCategory());
	}

	/**
	 * Adds a lost item to the system and to the current user's item database.
	 * The item added has a reward of $0.
	 * 
	 * @param name
	 *            is the name of the item.
	 * @param desc
	 *            is a description of the item.
	 * @param loc
	 *            is the location of the item.
	 */
	public void addLostItem(String name, String desc, String loc,
			String category) {
		addLostItem(name, desc, loc, category, 0d);
	}

	/**
	 * Adds a lost item to the system and the current user's database.
	 * 
	 * @param name
	 *            is the name of the item.
	 * @param desc
	 *            is a description of the item.
	 * @param loc
	 *            is the location of the item.
	 * @param reward
	 *            is the reward associated with the item.
	 */
	public void addLostItem(String name, String desc, String loc,
			String category, double reward) {
		LostItem item = new LostItem(name, desc, loc, currentUser, category,
				reward);

		ih.addItem(item);
		currentUser.addItem(item);

		try {
			ih.saveDatabase();
			lh.saveDatabase();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Adds a lost item to the system and to the current user's item database.
	 * This calls addFoundItem(String, String, String, String) using the
	 * specified item's attributes.
	 * 
	 * @param i
	 *            is the item to be added.
	 * @see addFoundItem(String, String, String, String)
	 */
	public void addFoundItem(FoundItem i) {
		addFoundItem(i.getName(), i.getDesc(), i.getLoc(), i.getItemCategory());
	}

	/**
	 * Adds a found item to the system and to the current user's item database.
	 * 
	 * @param name
	 *            is the name of the item.
	 * @param desc
	 *            is a description of the item.
	 * @param loc
	 *            is the location of the item.
	 */
	public void addFoundItem(String name, String desc, String loc,
			String category) {
		FoundItem item = new FoundItem(name, desc, loc, currentUser, category);

		ih.addItem(item);
		currentUser.addItem(item);

		try {
			ih.saveDatabase();
			lh.saveDatabase();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Returns the current user.
	 * 
	 * @return the current user
	 */
	public User getCurrentUser() {
		return currentUser;
	}

	/**
	 * Unlocks a locked user account.
	 * 
	 * @param username
	 *            is the username of the user to be unlocked
	 * @throws UserNotFoundException
	 *             if a user with the specified username does not exist.
	 */
	public void unlockUser(String username) throws UserNotFoundException {
		try {
			lh.unlockUser(username);
		} catch (LoginHandler.UserNotFoundException unfe) {
			throw unfe;
		}
	}

	/**
	 * Removes a user from the database.
	 * 
	 * @param username
	 *            is the username of the user to be deleted.
	 * @return true if the user was removed; false otherwise.
	 */
	public boolean deleteUser(String username) {
		return lh.deleteUser(username);
	}

	/**
	 * Returns a list of all items in the database.
	 * 
	 * @return a List of all Items in the database
	 */
	public List<Item> getItems() {
		return ih.getItems();
	}

	/**
	 * Returns a list of a specific user's items.
	 * 
	 * @param owner
	 *            is the user whose items should be returned.
	 * @return a list of owner's items.
	 */
	public List<Item> getItems(User owner) {
		return ih.getItems(owner);
	}

	/**
	 * Returns a list of the current user's items.
	 * 
	 * @return a list of the current user's items.
	 */
	public List<Item> getCurrentUserItems() {
		return ih.getItems(currentUser);
	}

	/**
	 * Returns a list of a specific user's owned items.
	 * 
	 * @param ownerUsername
	 *            is the username of the user.
	 * @return a list of items owned by a specific user.
	 */
	public List<Item> getItems(String ownerUsername) {
		return ih.getItems(lh.getUser(ownerUsername));
	}

	/**
	 * Checks if a user with a specified username exists.
	 * 
	 * @param username
	 *            is the username of the user to be checked.
	 * @return true if a user with the specified username exists; false
	 *         otherwise.
	 */
	public boolean userExists(String username) {
		return lh.userExists(username);
	}

	/**
	 * Adds a new user to the user database.
	 * 
	 * @param username
	 *            is the username the user should be created with.
	 * @param password
	 *            is the password the user should be created with.
	 * @param email
	 *            is the email address the user should be created with.
	 * @return true if the user is successfully created; false otherwise.
	 */
	public boolean createUser(String username, String password, String email) {
		return lh.createUser(username, password, email);
	}

	/**
	 * Returns a user with a specified username.
	 * 
	 * @param username
	 *            is the username of the user that should be returned.
	 * @return the user with the specified username if it exists; null
	 *         otherwise.
	 */
	public User getUser(String username) {
		return lh.getUser(username);
	}

	/**
	 * Wrapper for the LoginHander's attemptLogin method. For a more detailed
	 * description of what this does, refer to LoginHandler.attemptLogin().
	 * 
	 * @param username
	 *            is the username of the user who should be logged in.
	 * @param password
	 *            is the password of the user who should be logged in.
	 * @throws User.LockedException
	 *             if the user's account is locked.
	 * @throws User.WrongPasswordException
	 *             if the wrong password was entered.
	 * @throws UserNotFoundException
	 *             if the user does not exist.
	 */
	public void attemptLogin(String username, String password)
			throws User.LockedException, User.WrongPasswordException,
			UserNotFoundException {
		try {
			lh.attemptLogin(username, password);
			currentUser = lh.getUser(username);
		} catch (User.WrongPasswordException wpe) {
			throw wpe;
		} catch (User.LockedException le) {
			try {
				lh.saveDatabase();
			} catch (Exception e) {
				e.printStackTrace();
			}
			throw le;
		} catch (LoginHandler.UserNotFoundException unfe) {
			throw unfe;
		}
	}

	/**
	 * Logs the current user off of the system. This simply sets the current
	 * user pointer to null.
	 */
	public void logoff() {
		currentUser = null;
	}

	/**
	 * I like shorts because they are comfortable and easy to wear!
	 * 
	 * @return the found items
	 */
	public List<Item> getLostItems() {
		return ih.getLostItems();
	}

	/**
	 * Returns every submitted found item that is still open.
	 * 
	 * @return the found items
	 */
	public List<Item> getFoundItems() {
		return ih.getFoundItems();
	}

	/**
	 * Creates a new admin for the app.
	 * 
	 * @param username
	 * @param password
	 * @param email
	 * @return
	 */
	public boolean createAdmin(String username, String password, String email) {
		return lh.createAdmin(username, password, email);
	}

	/**
	 * returns a list of items filtered by a category
	 * 
	 * @param cat
	 * @return the items
	 */
	public List<Item> getItemsByCat(String cat) {
		return ih.getItemsByCat(cat);
	}
}